1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 package sun.nio.ch;
27
28 import java.io.*;
29 import java.lang.ref.*;
30 import java.net.*;
31 import java.nio.*;
32 import java.nio.channels.*;
33 import java.security.AccessController;
34 import java.security.PrivilegedExceptionAction;
35 import java.util.*;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 public class SocketAdaptor
51 extends Socket
52 {
53
54
55 private final SocketChannelImpl sc;
56
57
58 private volatile int timeout = 0;
59
60
61 private SocketAdaptor(SocketChannelImpl sc) {
62 this.sc = sc;
63 }
64
65 public static Socket create(SocketChannelImpl sc) {
66 return new SocketAdaptor(sc);
67 }
68
69 public SocketChannel getChannel() {
70 return sc;
71 }
72
73
74
75 public void connect(SocketAddress remote) throws IOException {
76 connect(remote, 0);
77 }
78
79 public void connect(SocketAddress remote, int timeout) throws IOException {
80 if (remote == null)
81 throw new IllegalArgumentException("connect: The address can't be null");
82 if (timeout < 0)
83 throw new IllegalArgumentException("connect: timeout can't be negative");
84
85 synchronized (sc.blockingLock()) {
86 if (!sc.isBlocking())
87 throw new IllegalBlockingModeException();
88
89 try {
90
91 if (timeout == 0) {
92 sc.connect(remote);
93 return;
94 }
95
96
97 SelectionKey sk = null;
98 Selector sel = null;
99 sc.configureBlocking(false);
100 try {
101 if (sc.connect(remote))
102 return;
103 sel = Util.getTemporarySelector(sc);
104 sk = sc.register(sel, SelectionKey.OP_CONNECT);
105 long to = timeout;
106 for (;;) {
107 if (!sc.isOpen())
108 throw new ClosedChannelException();
109 long st = System.currentTimeMillis();
110 int ns = sel.select(to);
111 if (ns > 0 &&
112 sk.isConnectable() && sc.finishConnect())
113 break;
114 sel.selectedKeys().remove(sk);
115 to -= System.currentTimeMillis() - st;
116 if (to <= 0) {
117 try {
118 sc.close();
119 } catch (IOException x) { }
120 throw new SocketTimeoutException();
121 }
122 }
123 } finally {
124 if (sk != null)
125 sk.cancel();
126 if (sc.isOpen())
127 sc.configureBlocking(true);
128 if (sel != null)
129 Util.releaseTemporarySelector(sel);
130 }
131
132 } catch (Exception x) {
133 Net.translateException(x, true);
134 }
135 }
136
137 }
138
139 public void bind(SocketAddress local) throws IOException {
140 try {
141 sc.bind(local);
142 } catch (Exception x) {
143 Net.translateException(x);
144 }
145 }
146
147 public InetAddress getInetAddress() {
148 SocketAddress remote = sc.remoteAddress();
149 if (remote == null) {
150 return null;
151 } else {
152 return ((InetSocketAddress)remote).getAddress();
153 }
154 }
155
156 public InetAddress getLocalAddress() {
157 if (sc.isOpen()) {
158 SocketAddress local = sc.localAddress();
159 if (local != null)
160 return ((InetSocketAddress)local).getAddress();
161 }
162 return new InetSocketAddress(0).getAddress();
163 }
164
165 public int getPort() {
166 SocketAddress remote = sc.remoteAddress();
167 if (remote == null) {
168 return 0;
169 } else {
170 return ((InetSocketAddress)remote).getPort();
171 }
172 }
173
174 public int getLocalPort() {
175 SocketAddress local = sc.localAddress();
176 if (local == null) {
177 return -1;
178 } else {
179 return ((InetSocketAddress)local).getPort();
180 }
181 }
182
183 private class SocketInputStream
184 extends ChannelInputStream
185 {
186 private SocketInputStream() {
187 super(sc);
188 }
189
190 protected int read(ByteBuffer bb)
191 throws IOException
192 {
193 synchronized (sc.blockingLock()) {
194 if (!sc.isBlocking())
195 throw new IllegalBlockingModeException();
196 if (timeout == 0)
197 return sc.read(bb);
198
199
200 SelectionKey sk = null;
201 Selector sel = null;
202 sc.configureBlocking(false);
203 try {
204 int n;
205 if ((n = sc.read(bb)) != 0)
206 return n;
207 sel = Util.getTemporarySelector(sc);
208 sk = sc.register(sel, SelectionKey.OP_READ);
209 long to = timeout;
210 for (;;) {
211 if (!sc.isOpen())
212 throw new ClosedChannelException();
213 long st = System.currentTimeMillis();
214 int ns = sel.select(to);
215 if (ns > 0 && sk.isReadable()) {
216 if ((n = sc.read(bb)) != 0)
217 return n;
218 }
219 sel.selectedKeys().remove(sk);
220 to -= System.currentTimeMillis() - st;
221 if (to <= 0)
222 throw new SocketTimeoutException();
223 }
224 } finally {
225 if (sk != null)
226 sk.cancel();
227 if (sc.isOpen())
228 sc.configureBlocking(true);
229 if (sel != null)
230 Util.releaseTemporarySelector(sel);
231 }
232
233 }
234 }
235 }
236
237 private InputStream socketInputStream = null;
238
239 public InputStream getInputStream() throws IOException {
240 if (!sc.isOpen())
241 throw new SocketException("Socket is closed");
242 if (!sc.isConnected())
243 throw new SocketException("Socket is not connected");
244 if (!sc.isInputOpen())
245 throw new SocketException("Socket input is shutdown");
246 if (socketInputStream == null) {
247 try {
248 socketInputStream = AccessController.doPrivileged(
249 new PrivilegedExceptionAction<InputStream>() {
250 public InputStream run() throws IOException {
251 return new SocketInputStream();
252 }
253 });
254 } catch (java.security.PrivilegedActionException e) {
255 throw (IOException)e.getException();
256 }
257 }
258 return socketInputStream;
259 }
260
261 public OutputStream getOutputStream() throws IOException {
262 if (!sc.isOpen())
263 throw new SocketException("Socket is closed");
264 if (!sc.isConnected())
265 throw new SocketException("Socket is not connected");
266 if (!sc.isOutputOpen())
267 throw new SocketException("Socket output is shutdown");
268 OutputStream os = null;
269 try {
270 os = AccessController.doPrivileged(
271 new PrivilegedExceptionAction<OutputStream>() {
272 public OutputStream run() throws IOException {
273 return Channels.newOutputStream(sc);
274 }
275 });
276 } catch (java.security.PrivilegedActionException e) {
277 throw (IOException)e.getException();
278 }
279 return os;
280 }
281
282 private void setBooleanOption(SocketOption<Boolean> name, boolean value)
283 throws SocketException
284 {
285 try {
286 sc.setOption(name, value);
287 } catch (IOException x) {
288 Net.translateToSocketException(x);
289 }
290 }
291
292 private void setIntOption(SocketOption<Integer> name, int value)
293 throws SocketException
294 {
295 try {
296 sc.setOption(name, value);
297 } catch (IOException x) {
298 Net.translateToSocketException(x);
299 }
300 }
301
302 private boolean getBooleanOption(SocketOption<Boolean> name) throws SocketException {
303 try {
304 return sc.getOption(name).booleanValue();
305 } catch (IOException x) {
306 Net.translateToSocketException(x);
307 return false;
308 }
309 }
310
311 private int getIntOption(SocketOption<Integer> name) throws SocketException {
312 try {
313 return sc.getOption(name).intValue();
314 } catch (IOException x) {
315 Net.translateToSocketException(x);
316 return -1;
317 }
318 }
319
320 public void setTcpNoDelay(boolean on) throws SocketException {
321 setBooleanOption(StandardSocketOptions.TCP_NODELAY, on);
322 }
323
324 public boolean getTcpNoDelay() throws SocketException {
325 return getBooleanOption(StandardSocketOptions.TCP_NODELAY);
326 }
327
328 public void setSoLinger(boolean on, int linger) throws SocketException {
329 if (!on)
330 linger = -1;
331 setIntOption(StandardSocketOptions.SO_LINGER, linger);
332 }
333
334 public int getSoLinger() throws SocketException {
335 return getIntOption(StandardSocketOptions.SO_LINGER);
336 }
337
338 public void sendUrgentData(int data) throws IOException {
339 synchronized (sc.blockingLock()) {
340 if (!sc.isBlocking())
341 throw new IllegalBlockingModeException();
342 int n = sc.sendOutOfBandData((byte)data);
343 assert n == 1;
344 }
345 }
346
347 public void setOOBInline(boolean on) throws SocketException {
348 setBooleanOption(ExtendedSocketOption.SO_OOBINLINE, on);
349 }
350
351 public boolean getOOBInline() throws SocketException {
352 return getBooleanOption(ExtendedSocketOption.SO_OOBINLINE);
353 }
354
355 public void setSoTimeout(int timeout) throws SocketException {
356 if (timeout < 0)
357 throw new IllegalArgumentException("timeout can't be negative");
358 this.timeout = timeout;
359 }
360
361 public int getSoTimeout() throws SocketException {
362 return timeout;
363 }
364
365 public void setSendBufferSize(int size) throws SocketException {
366
367 if (size <= 0)
368 throw new IllegalArgumentException("Invalid send size");
369 setIntOption(StandardSocketOptions.SO_SNDBUF, size);
370 }
371
372 public int getSendBufferSize() throws SocketException {
373 return getIntOption(StandardSocketOptions.SO_SNDBUF);
374 }
375
376 public void setReceiveBufferSize(int size) throws SocketException {
377
378 if (size <= 0)
379 throw new IllegalArgumentException("Invalid receive size");
380 setIntOption(StandardSocketOptions.SO_RCVBUF, size);
381 }
382
383 public int getReceiveBufferSize() throws SocketException {
384 return getIntOption(StandardSocketOptions.SO_RCVBUF);
385 }
386
387 public void setKeepAlive(boolean on) throws SocketException {
388 setBooleanOption(StandardSocketOptions.SO_KEEPALIVE, on);
389 }
390
391 public boolean getKeepAlive() throws SocketException {
392 return getBooleanOption(StandardSocketOptions.SO_KEEPALIVE);
393 }
394
395 public void setTrafficClass(int tc) throws SocketException {
396 setIntOption(StandardSocketOptions.IP_TOS, tc);
397 }
398
399 public int getTrafficClass() throws SocketException {
400 return getIntOption(StandardSocketOptions.IP_TOS);
401 }
402
403 public void setReuseAddress(boolean on) throws SocketException {
404 setBooleanOption(StandardSocketOptions.SO_REUSEADDR, on);
405 }
406
407 public boolean getReuseAddress() throws SocketException {
408 return getBooleanOption(StandardSocketOptions.SO_REUSEADDR);
409 }
410
411 public void close() throws IOException {
412 sc.close();
413 }
414
415 public void shutdownInput() throws IOException {
416 try {
417 sc.shutdownInput();
418 } catch (Exception x) {
419 Net.translateException(x);
420 }
421 }
422
423 public void shutdownOutput() throws IOException {
424 try {
425 sc.shutdownOutput();
426 } catch (Exception x) {
427 Net.translateException(x);
428 }
429 }
430
431 public String toString() {
432 if (sc.isConnected())
433 return "Socket[addr=" + getInetAddress() +
434 ",port=" + getPort() +
435 ",localport=" + getLocalPort() + "]";
436 return "Socket[unconnected]";
437 }
438
439 public boolean isConnected() {
440 return sc.isConnected();
441 }
442
443 public boolean isBound() {
444 return sc.localAddress() != null;
445 }
446
447 public boolean isClosed() {
448 return !sc.isOpen();
449 }
450
451 public boolean isInputShutdown() {
452 return !sc.isInputOpen();
453 }
454
455 public boolean isOutputShutdown() {
456 return !sc.isOutputOpen();
457 }
458
459 }